#pragma once

#include <d3d9.h>
#include <d3dx9tex.h>
#include <D3dx9core.h>
#include <list>
#include <map>
#include <string>
#include <time.h>

#include "Object.h"
#include "Unit.h"
#include "Env.h"
#include "Misc.h"
using namespace std;

/*****************************
Global Structs & Enums
*****************************/
struct INTPair {
	int x;
	int y;
};

struct FLOATPair {
	float x;
	float y;
};

enum BUTTON_CMD {
	NONE,
	NEW_MAP, OPEN_MAP, SAVE_MAP_AS, SAVE_MAP,
	UNIT_OBJECTS, ENV_OBJECTS, MISC_OBJECTS, LIGHT_OBJECT,
	PLACE_OBJECT, DELETE_OBJECT, GROUND_Y, PLAYER_Y,
	PLUS_LOCATION_X, MINUS_LOCATION_X, PLUS_LOCATION_Y, MINUS_LOCATION_Y, PLUS_LOCATION_Z, MINUS_LOCATION_Z,
	PLUS_ROTATION_X, MINUS_ROTATION_X, PLUS_ROTATION_Y, MINUS_ROTATION_Y, PLUS_ROTATION_Z, MINUS_ROTATION_Z,
	PLUS_SCALE_X, MINUS_SCALE_X, PLUS_SCALE_Y, MINUS_SCALE_Y, PLUS_SCALE_Z, MINUS_SCALE_Z,
	PLUS_LEVEL, MINUS_LEVEL,
	PLUS_ALIGNMENT, MINUS_ALIGNMENT,
	PLUS_VALUE, MINUS_VALUE,
	PLUS_CAN_MOVE, MINUS_CAN_MOVE,
	PLUS_STANCE, MINUS_STANCE,
	PLUS_PURPOSE, MINUS_PURPOSE,
	PLUS_HRADIUS, MINUS_HRADIUS,
	PLUS_ORDER, MINUS_ORDER,
	PLUS_GROUP, MINUS_GROUP,
	PLUS_SOUNDFILE, MINUS_SOUNDFILE,
	PLUS_LIGHT_DIR_X, MINUS_LIGHT_DIR_X, PLUS_LIGHT_DIR_Y, MINUS_LIGHT_DIR_Y,
	PLUS_LIGHT_DIR_Z, MINUS_LIGHT_DIR_Z,
	PLUS_LIGHT_DIF_R, MINUS_LIGHT_DIF_R, PLUS_LIGHT_DIF_G, MINUS_LIGHT_DIF_G,
	PLUS_LIGHT_DIF_B, MINUS_LIGHT_DIF_B,
	PLUS_LIGHT_SPE_R, MINUS_LIGHT_SPE_R, PLUS_LIGHT_SPE_G, MINUS_LIGHT_SPE_G,
	PLUS_LIGHT_SPE_B, MINUS_LIGHT_SPE_B,
	PLUS_LIGHT_AMB_R, MINUS_LIGHT_AMB_R, PLUS_LIGHT_AMB_G, MINUS_LIGHT_AMB_G,
	PLUS_LIGHT_AMB_B, MINUS_LIGHT_AMB_B,
	RESET_LIGHT,
	SCROLL_UP, SCROLL_DOWN, MODEL_ICON_BUTTON,
	DISPLAY_UNIT, DISPLAY_ENV, DISPLAY_MISC, DISPLAY_MAP,
	OPEN_MAP_ICON_BUTTON
};

struct BUTTON {
	int x;
	int y;
	int w;
	int h;
	BUTTON_CMD bCmd;
	LPDIRECT3DTEXTURE9 pic;
};

enum STATE {
	CLEAR,
	OPENING_MAP, SAVING_MAP_AS, SAVING_MAP,
	UNITS_MENU, ENV_MENU, MISC_MENU, LIGHT_MENU,
	UNIT_SELECTED, ENV_SELECTED, MISC_SELECTED
};

/*****************************
Global Variables
*****************************/
#define POLL_TIME					90
#define POLL_TIME2					70
#define FILE_NAME_LENGTH_MAX		252

HINSTANCE							hInstance = NULL;
HWND								wHandle = NULL;

LPDIRECT3D9							pD3D = NULL;
LPDIRECT3DDEVICE9					pd3dDevice = NULL;
D3DPRESENT_PARAMETERS				d3dpp;
ID3DXFont*							standardFont = NULL;
LPDIRECTINPUT8						dInput;					// the pointer to our DirectInput interface
LPDIRECTINPUTDEVICE8				dKeyboard;				// the pointer to the keyboard device
BYTE								dKey[256];				// the storage for the key-information
LPDIRECTINPUTDEVICE8				dMouse;					// the pointer to the mouse device
DIMOUSESTATE2						mouseState;				// the storage for the mouse-information
INTPair								mousePosition;
INTPair								prevMousePosition = {0,0};
time_t								now = 0, then = POLL_TIME;
time_t								now2 = 0, then2 = POLL_TIME2;

D3DLIGHT9							light;
D3DXVECTOR3							lightDir;

HRESULT								hr = NULL;

LPD3DXSPRITE						sprite = NULL;

int screenWidth =					1200;
int screenHeight =					800;
bool antialising =					true;

// camera variables
D3DXMATRIX							matView;
D3DXMATRIX							matProj;
D3DXVECTOR3							position;
D3DXVECTOR3							lookPos;

STATE								cState = CLEAR;

Unit								*selectedUnit = new Unit();
Env									*selectedEnv = new Env();
Misc								*selectedMisc = new Misc();

string								defaultObjectFilesSearch = "ObjectFiles\\Objects\\*.txt";
string								defaultFilesLocation = "ObjectFiles\\Objects\\";

string								soundFilesSearch = "Sound\\*.wav";
string								soundFilesLocation = "Sound\\";

string								openFilesSearch = "Maps\\*.wm";
string								openFilesLocation = "Maps\\";

bool								displayUnitList = true, displayEnvList = true, displayMiscList = true, displayMap = true;

char								inputSave[FILE_NAME_LENGTH_MAX];
int									inputSaveElement = 0;

float								mapScaleX = 0, mapScaleY = 0, mapScaleZ = 0;

// lists
// button lists
list<BUTTON>						MenuButtons;
list<BUTTON>						UnitButtons;
list<BUTTON>						EnvButtons;
list<BUTTON>						MiscButtons;
list<BUTTON>						LightButtons;
list<BUTTON>						UnitSideListButtons;
list<BUTTON>						EnvSideListButtons;
list<BUTTON>						MiscSideListButtons;
list<BUTTON>						DisplayOnOffSwitch;
list<BUTTON>						OpenMapButtons;

// option lists
list<string>						AlignmentList;
list<string>						CanMoveList;
list<string>						StanceList;
list<string>						PurposeList;
list<string>						SoundFilesList;

list<string>						DefaultFilesList;
list<string>						OpenFilesList;

list<Unit>							UnitObjects;
list<Env>							EnvObjects;
list<Misc>							MiscObjects;

list<Unit>							UnitList;
list<Env>							EnvList;
list<Misc>							MiscList;
Object								*MapObject;

list<char>							drawingSequenceType;
int									updateDrawingCounter = 0;

/*****************************
#defines
*****************************/
#define DIRECTINPUT_VERSION			0x0800
#define PROGRAM_VERSION				"Version1.5"

#define NormalWindow				(WS_OVERLAPPED		| \
									 WS_CAPTION			| \
									 WS_SYSMENU			| \
									 WS_MINIMIZEBOX)
									// WS_MAXIMIZEBOX & WS_THICKFRAME taken out so that the window cannot be resized

#define INITIAL_WINDOW_POSITION_X		450
#define INITIAL_WINDOW_POSITION_Y		100

#define OPEN_MAP_BOX_WIDTH				500
#define OPEN_MAP_BOX_HEIGHT				300
#define OPEN_MAP_NUM_DISPLAY			10

#define SAVE_AS_BOX_WIDTH				500
#define SAVE_AS_BOX_HEIGHT				100
#define SAVING_MAP_MSG_WIDTH			300
#define SAVING_MAP_MSG_HEIGHT			100

#define SPRITE_FILTER					D3DX_FILTER_NONE
#define SPRITE_MIP_FILTER				D3DX_FILTER_BOX

#define MENU_BUTTON_WIDTH				150
#define MENU_BUTTON_HEIGHT				80
#define SUBMENU_BUTTON_WIDTH			30
#define SUBMENU_BUTTON_HEIGHT			30
#define SUBMENU_BUTTON2_WIDTH			100
#define SUBMENU_BUTTON2_HEIGHT			30
#define BUTTON_TRANSPARENCY				D3DCOLOR_ARGB(255,255,0,0)
#define MODEL_ICON_WIDTH				100
#define MODEL_ICON_HEIGHT				50
#define MODEL_ICONS_VISIBLE				5

#define SUBBUTTON_GAP_WIDTH				120
#define BUTTON_GAP_WIDTH				70

#define FONT_HEIGHT						18
#define FONT_WEIGHT						650
#define FONT_COLOR						0xff000000
#define FONT_FORMAT						DT_LEFT|DT_NOCLIP

#define INITIALIZE_CAMERA_MOVE			D3DXVECTOR3(0.0f, 200.0f, -10.0f)
#define INITIALIZE_CAMERA_POINT			D3DXVECTOR3(0.0f, 1.0f, 0.0f)
#define NEAR_CLIP						0.0f
#define FAR_CLIP						1000.0f
#define CAMERA_MOVE_SPEED				2
#define CAMERA_ZOOM_SPEED				5

#define INITIAL_LIGHT_DIRECTION			D3DXVECTOR3(0.0f, -2.0f, 0.0f)
#define LIGHT_DIRECTION_CHANGE_SPEED	0.1
#define LIGHT_COLOR_CHANGE_SPEED		0.1

#define LOCATION_X_CHANGE				0.5f
#define LOCATION_Y_CHANGE				0.5f
#define LOCATION_Z_CHANGE				0.5f

#define ROTATION_X_CHANGE				5.0f
#define ROTATION_Y_CHANGE				5.0f
#define ROTATION_Z_CHANGE				5.0f

#define SCALE_X_CHANGE					0.2f
#define SCALE_Y_CHANGE					0.2f
#define SCALE_Z_CHANGE					0.2f

#define INITIAL_OBJECT_HEIGHT			1.0f
#define STANDARD_PLAYER_Y				50.0f

#define UPDATE_DRAWING_COUNTER_MAX		5

/*****************************
Global Functions
*****************************/
float degToRad(float deg) {
	return deg*(D3DX_PI/180.0f);
}

float radToDeg(float rad) {
	return rad*(180.0f/D3DX_PI);
}